package com.lhkj.ct.framework.shiro.realm;

import com.lhkj.ct.base.constants.SystemConstants;
import com.lhkj.ct.base.enums.DeleteStatus;
import com.lhkj.ct.base.enums.GlobalStatus;
import com.lhkj.ct.base.model.LoginUser;
import com.lhkj.ct.base.model.UserAuthInfo;
import com.lhkj.ct.base.utils.IpUtils;
import com.lhkj.ct.base.utils.ServletUtils;
import com.lhkj.ct.framework.shiro.token.UsernamePasswordAuthToken;
import com.lhkj.ct.meta.admin.mapper.SysEmployeeMapper;
import com.lhkj.ct.meta.admin.service.SysMenuService;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Set;

/**
 * <p>
 *     web登录授权
 * </p>
 */
public class AdminAuthorizingRealm extends AuthorizingRealm {

    private static final Logger log = LoggerFactory.getLogger(AdminAuthorizingRealm.class);

    @Resource
    private SysMenuService sysMenuService;

    @Resource
    private SysEmployeeMapper sysEmployeeMapper;

    public AdminAuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        super(cacheManager, matcher);
    }

    @Override
    public void setName(String name) {
        super.setName("admin_auth_realm");
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        if (!(token instanceof UsernamePasswordAuthToken)) return false;
        return Objects.equals(((UsernamePasswordAuthToken) token).getUserType(), Integer.valueOf(1));
    }

    /**
     * 授权权限
     *
     * 用户进行权限验证时候Shiro会去缓存中找,如果查不到数据,会执行这个方法去查权限,并放入缓存中
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        LoginUser user = (LoginUser) principals.getPrimaryPrincipal();
        authorizationInfo.setRoles(user.getShiroRoles());
        // 权限
        Set<String> perms = sysMenuService.getPermsByUserId(user);
        if (perms.isEmpty()) {
            throw new AuthenticationException("当前用户未配置系统访问权限！");
        }
        authorizationInfo.setStringPermissions(perms);
        return authorizationInfo;
    }

    /**
     * 用户身份验证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordAuthToken webToken = (UsernamePasswordAuthToken) token;
        String username = webToken.getUsername();
        UserAuthInfo user = sysEmployeeMapper.getUserAuthInfo(username);
        if (null == user) {
            throw new UnknownAccountException("账号或密码有误，请重新输入！");
        }
        if (user.getStatus() != GlobalStatus.NORMAL) {
            throw new DisabledAccountException("用户已封禁，请联系管理员！");
        }
        // 非超管判断机构是否禁用或删除
        if (!StringUtils.equals(SystemConstants.ROOT_LOGIN_NAME, username) && (user.getOrgStatus() != GlobalStatus.NORMAL || user.getOrgDelFlag() != DeleteStatus.NORMAL)) {
            throw new DisabledAccountException("机构已禁用或已删除！");
        }
        String ipAddr = IpUtils.getIpAddr();
        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        LoginUser loginUser = LoginUser.builder()
                .sessionKey(username)
                .userType(1)
                .userId(user.getUserId())
                .loginName(user.getUsername())
                .userName(user.getName())
                .deptId(user.getDeptId())
                .organId(user.getOrganId())
                .shiroRoles(user.getShiroRoles())
                .ipaddr(ipAddr)
                .loginLocation(IpUtils.getIpRegion(ipAddr))
                .loginTime(System.currentTimeMillis())
                .browser(userAgent.getBrowser().getName())
                .os(userAgent.getOperatingSystem().getName())
//                .roles(user.getRoles())
                .build();
        //4.设置账号为盐值
        ByteSource credentialsSalt = ByteSource.Util.bytes(SystemConstants.ACCOUNT_SALT);
        return new SimpleAuthenticationInfo(loginUser, user.getPassword(),credentialsSalt, getName());
    }

}
